package ai.fabu.dataplatform.service.GRPCServer;

import ai.fabu.dataplatform.*;
import ai.fabu.dataplatform.constant.ResultCode;
import ai.fabu.dataplatform.help.Result;
import ai.fabu.dataplatform.service.ApiForImportBagService;
import com.mongodb.MongoException;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.springboot.autoconfigure.grpc.server.GrpcService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.UncategorizedMongoDbException;
import org.springframework.transaction.TransactionSystemException;

import java.util.Random;

import static ai.fabu.dataplatform.constant.ConstantValue.PROCESSED_STATUS;
import static ai.fabu.dataplatform.constant.ConstantValue.PROCESS_FAILURE_STATUS;
import static ai.fabu.dataplatform.constant.ConstantValue.RETRY_TIME;

@Slf4j
public class DataPlatformTaskServer {
    @GrpcService(TaskServiceGrpc.class)
    private static class DataPlatformTaskImpl extends TaskServiceGrpc.TaskServiceImplBase{
        @Autowired
        ApiForImportBagService apiForImportBagService;

        @Override
        public void getTask(GetTaskRequest request, StreamObserver<Task> responseObserver) {
            Result<Task> result;
            try {
                result = apiForImportBagService.getTask(request.getId());
            } catch (Exception e) {
                FunctionUtil.errorHandler(responseObserver, "getTask", ResultCode.SYSTEM_ERROR.getMsg());
                throw e;
            }
            if(result.getCode() == ResultCode.SUCCESS.getCode()){
                responseObserver.onNext(result.getData());
                responseObserver.onCompleted();
            }
            else if(result.getCode() == ResultCode.NO_DATA.getCode()){
                log.info("getTask: no task can be get");
                Task task = Task.newBuilder().build();
                responseObserver.onNext(task);
                responseObserver.onCompleted();
            }
            else {
                FunctionUtil.errorHandler(result, responseObserver, "getTask");
            }
        }

        @Override
        public void updateTask(UpdateTaskRequest request, StreamObserver<Empty> responseObserver) {
            Result result;
            try{
                result = apiForImportBagService.updateTask(request);
            }
            catch (Exception e){
                FunctionUtil.errorHandler(responseObserver, "updateTask", ResultCode.SYSTEM_ERROR.getMsg());
                throw e;
            }

            if(result.getCode() == ResultCode.SUCCESS.getCode()){
                responseObserver.onNext(Empty.newBuilder().build());
                responseObserver.onCompleted();
                Status status = request.getStatus();
                if(status.getDoneBagNum() == status.getTotalBagNum() && status.getStatus().getNumber() == 0){
                    // bag record
                    try{
                        Result generateResult = apiForImportBagService.generateBagRecord(request.getId());
                        if(generateResult.getCode() != ResultCode.SUCCESS.getCode()){
                            log.error("updateTask: bag record generate fail");
                            apiForImportBagService.updateGroupTaskCompleteStatus(request.getId(), PROCESS_FAILURE_STATUS);
                            return;
                        }
                        else{
                            log.info("updateTask: bag record generate success");
                        }
                    } catch (Exception e){
                        apiForImportBagService.updateGroupTaskCompleteStatus(request.getId(), PROCESS_FAILURE_STATUS);
                        log.error("updateTask: bag record generate fail");
                        e.getStackTrace();
                        return;
                    }
                    // bag gps
                    try{
                        Result generateResult = apiForImportBagService.generateBagGPS(request.getId());
                        if(generateResult.getCode() != ResultCode.SUCCESS.getCode()){
                            log.error("updateTask: bag gps generate fail");
                            apiForImportBagService.updateGroupTaskCompleteStatus(request.getId(), PROCESS_FAILURE_STATUS);
                            return;
                        }
                        else{
                            log.info("updateTask: bag gps generate success");
                        }
                    } catch (Exception e){
                        apiForImportBagService.updateGroupTaskCompleteStatus(request.getId(), PROCESS_FAILURE_STATUS);
                        log.error("updateTask: bag gps generate fail");
                        e.getStackTrace();
                        return;
                    }

                    // static map mileage
                    try{
                        Result generateResult = apiForImportBagService.generateGroupMapAndMileage(request.getId());
                        if(generateResult.getCode() != ResultCode.SUCCESS.getCode()){
                            log.error("updateTask: static map or mileage generate fail");
                            apiForImportBagService.updateGroupTaskCompleteStatus(request.getId(), PROCESS_FAILURE_STATUS);
                            return;
                        }
                        else{
                            log.info("updateTask: static map and mileage generate success");
                        }
                    } catch (Exception e){
                        apiForImportBagService.updateGroupTaskCompleteStatus(request.getId(), PROCESS_FAILURE_STATUS);
                        log.error("updateTask: static map or mileage generate fail");
                        e.getStackTrace();
                        return;
                    }
//                    apiForImportBagService.updateGroupTaskCompleteStatus(request.getId(), PROCESSED_STATUS);
                }
            }
            else {
                FunctionUtil.errorHandler(result, responseObserver, "updateTask");
            }
        }
    }
}
